package de.lns.render;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;


/**
 * This class is the visual representation of an Entity.
 *
 */
public class Model {
	private Drawable source;
	private Layer[] layers;
	private int[] animStates;
	private int size;
	private int animCounter;
	
	public Model(Drawable src, int layerCount) {
		size = 0;
		animCounter = 0;
		source = src;
		layers = new Layer[layerCount];
		animStates = new int[0];
	}
	
	public Model(Drawable src, int layerCount, int animCount) {
		size = 0;
		animCounter = 0;
		source = src;
		layers = new Layer[layerCount];
		animStates = new int[animCount];
	}
	
	public void animState(int index, int state){
		if(index<animStates.length)
			animStates[index] = state;
	}
	
	protected void addLayer(Layer l){
		if(size<layers.length){
			layers[size] = l;
			size++;
			if(l instanceof AnimatedLayer){
				animCounter++;
			}
		}
	}

	protected int getAnimCounter() {
		return animCounter;
	}
	
	protected int[] getAnimStates(){
		return animStates;
	}
	
	protected int getSize(){
		return size;
	}
	
	protected float getX(){
		return (float)source.getPosX();
	}
	
	protected float getY(){
		return (float)source.getPosY();
	}
	
	protected float getZ(){
		return (float)source.getPosZ();
	}
	
	protected float getRotation(){
		return (float)source.getDirection();
	}
	
	protected float getScale(){
		return (float)source.getScale();
	}
	
	protected void render() {
		if(source.alignRel()){
			float ratio = Renderer.getMapRatio();
			glUniform1f(Renderer.shader.f_scale, (float)source.getScale()*ratio);
			glUniform1f(Renderer.shader.f_angle, (float)source.getDirection());
			glUniform3f(Renderer.shader.f3_displacement, (float)source.getPosX()*ratio, (float)source.getPosY()*ratio, (float)source.getPosZ());
		} else{
			glUniform1f(Renderer.shader.f_scale, (float)source.getScale());
			glUniform1f(Renderer.shader.f_angle, (float)source.getDirection());
			glUniform3f(Renderer.shader.f3_displacement, (float)source.getPosX(), (float)source.getPosY(), (float)source.getPosZ());
		}
		
		glBindTexture(GL_TEXTURE_2D, source.getTextureID());
		
		writeLayerVertices();
		writeLayerMapping();
		
		glEnableClientState(GL_VERTEX_ARRAY);
		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
		
		glDrawArrays(GL_TRIANGLES, 0, layers.length*6);

		glDisableClientState(GL_VERTEX_ARRAY);
		glDisableClientState(GL_VERTEX_ARRAY);
		
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindTexture(GL_TEXTURE_2D, 0);
	}

	private void writeLayerVertices() {
		glBindBuffer(GL_ARRAY_BUFFER, Renderer.vertexPointer());
		
		for(int i = 0; i<layers.length; i++){
			layers[i].writeVertices(i*12);
		}
		
		glVertexPointer(2, GL_FLOAT, 0, 0);
		return;
	}

	private void writeLayerMapping() {
		glBindBuffer(GL_ARRAY_BUFFER, Renderer.mappingPointer());
		
		for(int i = 0; i<layers.length; i++){
			layers[i].writeMapping(i*12);
		}
		
		glTexCoordPointer(2, GL_FLOAT, 0, 0);
		return;
	}
}
